import lib.system.mlf.FlowProcessor;

var flowProcessor=FlowProcessor.getInstance();

// var currentBlockNum;
var timestampArray:Array;
var baseTime:Number=0;
// var blockStartTime:Number;
var recordFlag:Boolean;
var fixedTime:Boolean;

var recordedFlag:Boolean;	// record the whole content or not
var status:String;

function initializeTimestamp()
{
	timestampArray=new Array();
	var tsArr=Packages.modula.task.Composition.processData.timestamp;
	for (var i=0; i<tsArr.length; i++)
	{
		timestampArray.push(Number(tsArr[i])*1000);
	}
	baseTime=10;
	// Packages.log("initializeTimeStamp: "+timestampArray, "debug");
}

function record(rd:Boolean, owner:String):Boolean
{	
	// permission -> status -> operation -> appearance
	if (Packages.modula.task.Composition.audioId==null)
	{
		Packages.modula.MessageCenter.send("NO_AVAILABLE_AUDIOID", 1, 0);
		return false;
	}

	recordFlag=rd;

	// Collab Permission Condition
	if (Packages.model.UserProfile.recordingCollabFlag)
	{
		if (recordFlag)
		{
			if (Packages.modula.task.Composition.speakerHolder!=null)
			{
				Packages.modula.MessageCenter.send("NO_IDLE_MICROPHONE", 1, 0);
				return false;
			}
		}
		else
		{
			/*if (Packages.modula.task.Composition.speakerHolder!=owner)
			{
				Packages.modula.MessageCenter.send("YOU_ARE_NOT_THE_SPEAKERHOLDER", 1, 0);
				return false;
			}*/
		}
	}

	if (recordFlag)
	{	
		// start/resume recording, so no whole content recorded
		recordedFlag=false;
		// start/resume recording, so recording status
		status="recording";
		
		// check resume or start
		if (baseTime>0)
		{
			// Packages.log("resume", "debug");
			// resume (special resume, remove some blocks and append new following)

			var currentBlockNum=Packages.modula.RTxtReader.accessBlockInfo().current;
			// Packages.log("currentBlockNum: "+currentBlockNum, "debug");
			var appendTimestamp;
			if (currentBlockNum>=0)		// added '0' case now
			{
				// before
				// 2008-11-23 see .svn v388
				// 2008-11-28 clear up
				// 2008-11-28 added +2000 offset for debug case
				if (currentBlockNum==timestampArray.length-1) appendTimestamp=timestampArray[timestampArray.length-1]+2000;
				else appendTimestamp=timestampArray[currentBlockNum-1];

			}
			// Packages.log("appendTimestamp: "+appendTimestamp, "debug");

			baseTime=getTimer()-appendTimestamp;
			// Packages.log("baseTime: "+baseTime, "debug");

			fixedTime=false;

			if (Packages.model.UserProfile.recordingCollabFlag)
			{
				baseTime+=2000;	// 2008-12-1 @tmp for fix sync, # flag, in collab env
				// collab env, resume operation
				if (owner==Packages.model.UserProfile.data.nickName)
				{
					// SpeakerHolder
					// unsubscribe self, resume recording
					Packages.modula.MicrophoneDevice.unsubscribe();//
					// no '#' now in the collab env, but use now
					Packages.modula.MicrophoneDevice.resume(Packages.modula.task.Composition.audioId+"#"+appendTimestamp, true);

					Packages.modula.task.Composition.speakerHolder=owner;
				}
				else
				{
					// do nothing by other members
					// keep subscribing - strong
					Packages.modula.MicrophoneDevice.subscribe(Packages.modula.task.Composition.audioId, true);
				}
			}
			else
			{
				// solo env, resume operation
				Packages.modula.MicrophoneDevice.resume(Packages.modula.task.Composition.audioId+"#"+appendTimestamp);
			}
		}
		else 
		{
			// start
			// startRecord(Packages.task.Composition.audioId);
			if (Packages.model.UserProfile.recordingCollabFlag)
			{
				// collab env, publish operation
				if (owner==Packages.model.UserProfile.data.nickName)
				{
					// SpeakerHolder
					// unsubscribe self, resume recording
					Packages.modula.MicrophoneDevice.unsubscribe();//
					Packages.modula.MicrophoneDevice.publish(Packages.modula.task.Composition.audioId, "record", true);

					Packages.modula.task.Composition.speakerHolder=owner;
				}
				else
				{
					// other members, start subscribing
					Packages.modula.MicrophoneDevice.subscribe(Packages.modula.task.Composition.audioId, true);
				}
			}
			else
			{
				Packages.modula.MicrophoneDevice.publish(Packages.modula.task.Composition.audioId, "record");
			}

			timestampArray=new Array();
			baseTime=getTimer();
			// Packages.log(Packages.model.UserProfile.data.nickName+".startRecord.common.baseTime: "+baseTime);
			fixedTime=false;
		}
	}
	else 
	{
		// pause or stop (flush while publish)
		status="pause";

		if (Packages.model.UserProfile.recordingCollabFlag)
		{
			// collab env, unpublish operation, subscribe operation
			if (owner==Packages.model.UserProfile.data.nickName)
			{	
				Packages.modula.MicrophoneDevice.unpublish(true);

				Packages.modula.task.Composition.speakerHolder=null;
				Packages.modula.MicrophoneDevice.subscribe(Packages.modula.task.Composition.audioId, true);

				// save the audio and task while idle for a period of time
				autoSaveCollabRecording();
			}
			else
			{
				// other members, do nothing
			}
			Packages.modula.RTxtReader.switchBlock(0, true);
			generateTimestampData();
		}
		else
		{
			Packages.modula.MicrophoneDevice.close();
		
			Packages.modula.RTxtReader.switchBlock(0, true);
			fixedTime=true;
			// displayTimestampArray();
			generateTimestampData();
			saveAudio("flv");
		}
	}

	return true;
}

function autoSaveCollabRecording()
{
	if (!Packages.modula.task.Composition.host) return;
	
	Packages.system.mlf.GateKeeper.addListener("onAutoSaveIdleEvent", this);
	
	var noticeEvent:Object=new Object();
	noticeEvent.type="onAutoSaveIdleEvent";
	noticeEvent.gap=10;
	noticeEvent.count=0;
	Packages.system.display.Timer.regNoticeEvent(noticeEvent);
}

function onAutoSaveIdleEvent(evt:Object)
{
	if (status=="recording")
	{
		// not enough idle time to save
	}
	else if (status=="pause")
	{
		Packages.modula.MessageCenter.send("AUTO_SAVE_COLLAB_RECORDING", 1, 0);
		Packages.modula.task.Common.sendMsg("AUTO_SAVE_COLLAB_RECORDING");
		
		fixedTime=true;
		saveAudio("flv");
	}

	Packages.system.mlf.GateKeeper.removeListener("onAutoSaveIdleEvent", this);
	Packages.system.display.Timer.removeNoticeEvent("onAutoSaveIdleEvent");
}

function addTimeStamp(preOffsetFlag:Boolean, currentBlockNum:Number)
{
	if (fixedTime) return;
	timestampArray[currentBlockNum]=getTimer()-baseTime;
	// Packages.log("timestampArray["+currentBlockNum+"].time: "+timestampArray[currentBlockNum], "debug");
	if (preOffsetFlag) timestampArray[currentBlockNum]-=2000;
}

function generateTimestampData()
{
	var pointStr:String="";
	for (var i=0; i<timestampArray.length; i++)
	{
		pointStr+=String(Math.floor(timestampArray[i]/1000));
		if (i<timestampArray.length-1)
		{
			pointStr+=";";
		}
		else Packages.modula.task.Composition.processData.duration=Math.floor(timestampArray[i]/1000);
	}
	// Packages.log("pointStr: "+pointStr, "debug");
	Packages.modula.task.Composition.processData.timestamp=pointStr;
	var progress=Packages.modula.RTxtReader.accessBlockInfo();
	// Packages.log("progress: "+(progress.current+1)+" / "+progress.total, "debug");

	if ((progress.current+1)==progress.total)
	{
		Packages.modula.MessageCenter.send("RECORDING_ALL_BLOCKS", 1, 0);
		recordedFlag=true;
	}
}

function clear()
{
	delete timestampArray;
	baseTime=0;
	fixedTime=true;
	delete recordFlag;
}

function publish(publishItemStatus:Object)
{
	/*// Packages.log("publish in the Processor...", "debug");
	for (var a in publishItemStatus)
	{
		// Packages.log(a+": "+publishItemStatus[a], "debug");
	}*/

	Packages.system.mlf.GateKeeper.addListener("noTick", this);
	flowProcessor.regRules("PublishReadingMaterial");

	if (publishItemStatus.textFmtSpot)
	{
		flowProcessor.regEvent("onPublishText");
		Packages.system.mlf.GateKeeper.addListener("onPublishText", this);
	}

	if (publishItemStatus.mp3FmtSpot)
	{
		flowProcessor.regEvent("onPublishMP3");
		Packages.system.mlf.GateKeeper.addListener("onPublishMP3", this);
	}

	if (publishItemStatus.aacFmtSpot)
	{
		flowProcessor.regEvent("onPublishAAC", null);
		Packages.system.mlf.GateKeeper.addListener("onPublishAAC", this);
	}

	if (publishItemStatus.webFmtSpot)
	{
		flowProcessor.regEvent("onPublishSync");
		Packages.system.mlf.GateKeeper.addListener("onPublishSync", this);
	}

	if (publishItemStatus.swfFmtSpot)
	{
		flowProcessor.regEvent("onPublishSWF", null);
		Packages.system.mlf.GateKeeper.addListener("onPublishSWF", this);
	}

	if (publishItemStatus.zipFmtSpot)
	{
		flowProcessor.regEvent("onPublishZip");
		Packages.system.mlf.GateKeeper.addListener("onPublishZip", this);
	}

	flowProcessor.regEvent("onPublishTask");
	Packages.system.mlf.GateKeeper.addListener("onPublishTask", this);

	flowProcessor.launchEvent();
}

function noTick(obj)
{
	Packages.system.mlf.GateKeeper.removeListener("noTick", this);
}

function onPublishSWF(obj)
{
	Packages.system.mlf.GateKeeper.removeListener("onPublishSWF", this);
	Packages.system.mlf.GateKeeper.dispatchMessage({type:"onPublishReadingMaterial", scope:"swf", result:"Done"});
	flowProcessor.launchEvent();
}

function onPublishText(obj)
{
	Packages.system.mlf.GateKeeper.removeListener("onPublishText", this);
	// Packages.log("onPublishText: "+obj.param, "debug");
	Packages.system.mlf.GateKeeper.dispatchMessage({type:"onPublishReadingMaterial", scope:"text", result:"Done"});
	flowProcessor.launchEvent();
}

function onPublishMP3(obj)
{
	Packages.system.mlf.GateKeeper.removeListener("onPublishMP3", this);
	Packages.system.mlf.GateKeeper.dispatchMessage({type:"onPublishReadingMaterial", scope:"mp3", result:"Done"});
	flowProcessor.launchEvent();
}

function onPublishSync(obj)
{
	Packages.system.mlf.GateKeeper.removeListener("onPublishSync", this);
	var obj:Object=new Object();

	obj.audioUuid=Packages.modula.task.Composition.filteredAudioId.toString();
	obj.deployType="mp3/unpackaged";
	obj.vendor="Nokia";
	obj.model="N95";

	var data:Object=new Object();
	data.scope="web";

	Packages.modula.RequestCommand.request("REMOTING", "audioDeploy", obj, null, null, this, data);
}

function onPublishZip(obj)
{
	Packages.system.mlf.GateKeeper.removeListener("onPublishZip", this);

	var obj:Object=new Object();

	obj.audioUuid=Packages.modula.task.Composition.filteredAudioId.toString();
	obj.deployType="swf/packaged";
	obj.vendor="Nokia";
	obj.model="N95";

	var data:Object=new Object();
	data.scope="zip";

	Packages.modula.RequestCommand.request("REMOTING", "audioDeploy", obj, null, null, this, data);
}

function onPublishAAC(obj)
{
	Packages.system.mlf.GateKeeper.removeListener("onPublishAAC", this);

	var obj:Object=new Object();

	obj.audioUuid=Packages.modula.task.Composition.filteredAudioId.toString();
	obj.deployType="aac/packaged";
	obj.vendor="Nokia";
	obj.model="N95";

	var data:Object=new Object();
	data.scope="aac";

	Packages.modula.RequestCommand.request("REMOTING", "audioDeploy", obj, null, null, this, data);
}

function onPublishTask(obj)
{
	Packages.system.mlf.GateKeeper.removeListener("onPublishTask", this);

	var obj:Object=new Object();
	obj.recordTaskId=Packages.modula.task.Composition.currentTask.recordTaskId.toString();

	Packages.modula.RequestCommand.request("REMOTING", "recordTaskPublish", obj, null, null, this, null);
}

function saveAudio(type:String)
{
	// Packages.log("saveAudio: "+type, "debug");
	if (type=="mp3")
	{
		// createAudio("mp3");
		invokeCreateAudio("mp3", Packages.modula.task.Composition.syncId);
		return;
	}
	
	// if (Packages.modula.task.Composition.currentTask.status=="1")
	if (Packages.modula.task.Composition.audioId==Packages.modula.task.Composition.latestAudio.uuid)
	{
		// updateAudio
		updateAudio();
	}	
	else 
	{
		// createAudio
		createAudio("flv");
	}
}

function updateAudio()
{
	//public Result syncUpdate(String syncID, String content);
	var obj:Object=new Object();
	obj.syncId=Packages.modula.task.Composition.syncId.toString();
	obj.content=generateMLVbyWork();

	var data:Object=new Object();
	data.invokeCall="updateAudioAfterSync";

	Packages.modula.RequestCommand.request("REMOTING", "syncUpdate", obj, null, null, this, data);
}

function updateAudioAfterSync()
{
	//public Result audioUpdate(String audioID, String syncID, String name, String duration, String memberID, String collabMemberIDs);
	var obj:Object=new Object();
	obj.audioId=Packages.modula.task.Composition.flvAudioId.toString();
	obj.syncId=Packages.modula.task.Composition.syncId.toString();
	obj.name="flv source file updated";
	obj.duration=Packages.modula.task.Composition.processData.duration.toString();

	obj.memberId=Packages.model.UserProfile.data.memberId.toString();
	obj.collabMemberIds=Packages.modula.task.Composition.collabMembers;

	var data:Object=new Object();
	data.invokeCall="invokeUpdateTask";
	data.invokeArgs=new Array();
	data.invokeArgs.push("flv");
	data.invokeArgs.push(Packages.modula.task.Composition.flvAudioId);

	Packages.modula.RequestCommand.request("REMOTING", "audioUpdate", obj, null, null, this, data);
}

function createAudio(type:String)
{
	var obj:Object=new Object();

	var data:Object=new Object();
	data.invokeCall="publishSyncFile";
	data.invokeArgs=new Array();
	data.invokeArgs.push(type);

	Packages.modula.RequestCommand.request("REMOTING", "generateUuid", obj, null, null, this, data);
}

function publishSyncFile(type:String, uuid:String)
{
	var obj:Object=new Object();
	obj.uuid=uuid;
	obj.content=generateMLVbyWork();

	var data:Object=new Object();
	data.invokeCall="invokeCreateAudio";
	data.invokeArgs=new Array();
	data.invokeArgs.push(type);

	Packages.modula.RequestCommand.request("REMOTING", "syncCreate", obj, null, null, this, data);
}

function invokeCreateAudio(type:String, syncId:String)
{
	// Packages.log("invokeCreateAudio: "+type, "debug");

	Packages.modula.task.Composition.syncId=syncId;
	
	var obj:Object=new Object();
	obj.recordTaskId=Packages.modula.task.Composition.currentTask.recordTaskId.toString();
	obj.syncId=syncId.toString();
	if (type=="mp3") obj.flvAudioId=Packages.modula.task.Composition.flvAudioId.toString();
	obj.type="1";
	if (type=="mp3") obj.subtype="1";
	else if (type=="flv") obj.subtype="3";
	obj.name=type+" source file";
	if (type=="flv")
	{
		obj.uuid=Packages.modula.task.Composition.audioId.toString();
	}
	else if (type=="mp3")
	{
		obj.uuid=Packages.modula.task.Composition.filteredAudioId.toString();	// new filteredAudioId
	}
	obj.memberId=Packages.model.UserProfile.data.memberId.toString();
	obj.collabMemberIds=Packages.modula.task.Composition.collabMembers;
	obj.duration=Packages.modula.task.Composition.processData.duration.toString();

	var data:Object=new Object();
	data.invokeCall="invokeUpdateTask";
	data.invokeArgs=new Array();
	data.invokeArgs.push(type);

	Packages.modula.RequestCommand.request("REMOTING", "audioCreate", obj, null, null, this, data);
}

function invokeUpdateTask(type:String, latestAudioId:String)
{
	var obj:Object=new Object();
	
	obj.recordTaskId=Packages.modula.task.Composition.currentTask.recordTaskId.toString();
	if (type=="flv")
	{
		if (recordedFlag)
		{
			obj.status="2";
		}
		else obj.status="1";
	}
	else if (type=="mp3") obj.status="3";

	obj.latestAudioId=latestAudioId.toString();

	// if task not changed, no request more

	Packages.modula.RequestCommand.request("REMOTING", "recordTaskUpdate", obj, null, null, this, null);
}

function generateMLVbyWork():String
{
	var mlvString:String="";
	var duration:Number=Packages.modula.task.Composition.processData.duration;
	var blockMin=Packages.modula.task.Composition.readerSettings.block.size?Packages.task.Composition.readerSettings.block.size:100;
	var bookUUID=Packages.modula.task.Composition.contentId;
	var audioUUID=Packages.modula.task.Composition.filteredAudioId?Packages.modula.task.Composition.filteredAudioId:Packages.modula.task.Composition.audioId;
	mlvString+="<mlv duration='"+duration+"' name='MLV' info='designed by blue night'>";
	mlvString+="<resource>";
	mlvString+="<ext name='txtreader' uri='app/txtReader.swf'/>";
	mlvString+="<ext name='txtsync' uri='app/txtSync.swf'/>";
	mlvString+="<txtreader name='chapter_c1' uri='$[book:"+bookUUID+"]'/>";
	mlvString+="<txtsync name='chapter_s1' size='-1'>";
	mlvString+="<sync blockMin='"+blockMin+"'>";
	mlvString+="<point>"+Packages.modula.task.Composition.processData.timestamp+"</point>";
	mlvString+="</sync>";
	mlvString+="</txtsync>";
	mlvString+="<$[format] name='chapter_a1' uri='$[audio:"+audioUUID+"]'/>";
	mlvString+="</resource>";
	mlvString+="<playback>";
	mlvString+="<clip name='chapter_a1_c1' signpost='1' length='"+duration+"' layer='10' ref='chapter_a1'/>";
	mlvString+="<clip name='chapter_c1_c1' signpost='1' length='"+duration+"' layer='5' ref='chapter_c1'/>";
	mlvString+="<clip name='chapter_s1_c1' signpost='1' length='"+duration+"' layer='15' ref='chapter_s1' option='1'/>";
	mlvString+="</playback>";
	mlvString+="</mlv>";

	return mlvString;
}

function handleResponseResult(rsp:Object)
{
	Packages.log("rsp.service.method: "+rsp.service.method, "debug");
	var rst=rsp.service.result;
	for (var a in rst)
	{
		Packages.log(a+": "+rst[a], "debug");
	}

	if (rsp.service.method=="generateUuid")
	{
		// rsp.component.data.invokeArgs=new Array();
		rsp.component.data.invokeArgs.push(rsp.service.result.returnObj);
	}
	else if (rsp.service.method=="syncCreate")
	{
		// rsp.service.result as syncId
		// rsp.component.data.invokeArgs=new Array();
		rsp.component.data.invokeArgs.push(rsp.service.result.returnObj);
	}
	else if (rsp.service.method=="audioCreate")
	{
		Packages.modula.task.Composition.flvAudioId=rsp.service.result.returnObj;
		rsp.component.data.invokeArgs.push(rsp.service.result.returnObj);
	}
	else if (rsp.service.method="audioDeploy")
	{
		var rst:String;

		if (rsp.service.result.returnCode==0)
		{
			rst="Done";
		}
		else rst="Failed";
		Packages.system.mlf.GateKeeper.dispatchMessage({type:"onPublishReadingMaterial", scope:rsp.component.data.scope, result:rst});
		flowProcessor.launchEvent();
	}
	else if (rsp.service.method=="recordTaskPublish")
	{
		if (rsp.service.result.returnCode==0)
		{
			rst="Done";
		}
		else rst="Failed";
		Packages.system.mlf.GateKeeper.dispatchMessage({type:"onPublishReadingMaterial", scope:"all", result:rst});
		flowProcessor.launchEvent();
	}
	else if (rsp.service.method=="recordTaskUpdate")
	{
		if (rsp.service.result.returnCode==0)
		{
			Packages.modula.MessageCenter.send("AUTO_SAVE_COLLAB_RECORDING_SUCCESS", 1, 0);
			Packages.modula.task.Common.sendMsg("AUTO_SAVE_COLLAB_RECORDING_SUCCESS");
		}
		else 
		{
			Packages.modula.MessageCenter.send("AUTO_SAVE_COLLAB_RECORDING_FAILED", 1, 0);
			Packages.modula.task.Common.sendMsg("AUTO_SAVE_COLLAB_RECORDING_FAILED");
		}
	}

	if (rsp.component.data.invokeCall!=null)
	{
		this[rsp.component.data.invokeCall].apply(this, rsp.component.data.invokeArgs);
	}
}